package com.wn.service.net

import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.LogUtils
import com.google.gson.Gson
import com.wn.common.net.model.DataResult
import com.wn.common.net.model.Error
import com.wn.common.net.model.Success
import com.wn.common.net.model.isSuccess
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

/**
 * @Author: wn
 * @Date: 2023/3/23 16:03
 * @Description: 将 BaseResponse 转化为需要的对象类型
 */
/**
 * 这里表示网络请求成功，并得到业务服务器的响应
 * @receiver BaseResponse  转化为需要的对象类型，也就是将data.string转为entity
 * @return T? 可能为null，如果json解析失败的话
 *
 * BaseResponse to Entity
 *
 * 加了reified才可以T::class.java
 */
inline fun <reified T> BaseResponse<T>.toEntity(): T? {
  if (result == null) {
    LogUtils.e("server Response Json Ok,But data==null, $code, $msg")
    return null
  }

  // TODO 如果有需要的话在这里对返回的data数据进行解密然后再 tojson fromjson

/*  val decodeData = decodeData(data.toString())
  // gson不允许我们将json对象采用String,所以单独处理
  if (T::class.java.isAssignableFrom(String::class.java)) {
    return decodeData as T
  }*/

  /**
   * 如果data不为空，先进行tojson处理再转化为T对象类型的entity string
   * 传入 对应的  entity -- T
   */
  return runCatching {
    GsonUtils.fromJson(Gson().toJson(result), T::class.java)
  }.onFailure {
    it.printStackTrace() // Catch出错，报错
  }
    .getOrNull()
}

/**
 * 接口成功且业务成功code==SUCCESS的情况
 * @receiver BaseResponse
 * @param block 传入 lambda 获取 code 与 message  data--T
 * @return BaseResponse
 */
@OptIn(ExperimentalContracts::class)
inline fun <reified T> BaseResponse<T>.onBizOK(block: (code: Int, data: T?, message: String?) -> Unit): BaseResponse<T> {
  contract {
    callsInPlace(block, InvocationKind.AT_MOST_ONCE)
  }
  if (code == BaseResponse.SERVER_CODE_SUCCESS || code == BaseResponse.SERVER_CODE_SUCCESS1)
    block(code, this.toEntity(), msg)
  return this
}

/**
 * 接口成功，但是业务返回code不是1或1001的情况
 * @receiver BaseResponse
 * @param block 传入 lambda 获取 code 与 message
 * @return BaseResponse
 */
@OptIn(ExperimentalContracts::class)
inline fun <T> BaseResponse<T>.onBizError(block: (code: Int, message: String?) -> Unit): BaseResponse<T> {
// 函数参数将被 最多调用一次
  contract {
    callsInPlace(block, InvocationKind.AT_MOST_ONCE)
  }
  // 同时不等于 1 和 1001
  if (code != BaseResponse.SERVER_CODE_SUCCESS && code != BaseResponse.SERVER_CODE_SUCCESS1) {
    block(code, msg ?: "Error Message Null")
  }
  return this
}

/**
 * 扩展用于处理网络返回数据结果 网络接口请求成功，但是业务成功与否不一定
 * @receiver DataResult
 * @param block 传入 lambda 获取  data--T  lambda中 this指向 T
 * @return DataResult
 */
@OptIn(ExperimentalContracts::class)
@Suppress("UNCHECKED_CAST")
inline fun <T> DataResult.onSuccess(block: T.() -> Unit): DataResult {
  contract {
    callsInPlace(block, InvocationKind.AT_MOST_ONCE)
  }
  if (isSuccess)
    ((this as Success<*>).data as T).block()
  return this
}

/**
 * 扩展用于处理网络返回数据结果 网络请求出现错误的时候的回调
 * @receiver DataResult
 * @param block 传入 lambda 获取  Throwable  lambda中 this指向 Throwable
 * @return DataResult
 */
@OptIn(ExperimentalContracts::class)
inline fun DataResult.onFailure(block: Throwable.() -> Unit): DataResult {
  contract {
    callsInPlace(block, InvocationKind.AT_MOST_ONCE)
  }
  if (this is Error)
    exception.block()
  return this
}